using System;
using System.Collections.ObjectModel;
using System.Linq;
using CommunityToolkit.Mvvm.Input;

namespace AnimationPage.ViewModels;

public partial class ChatMessageListViewModel : ViewModelBase
{
    #region Protected Members

    /// <summary>
    /// The last searched text in this list
    /// </summary>
    protected string mLastSearchText;

    /// <summary>
    /// The text to search for in the search command
    /// </summary>
    protected string mSearchText;


    /// <summary>
    /// The chat thread items for the list
    /// </summary>
    protected ObservableCollection<ChatMessageListItemViewModel> mItems;

    /// <summary>
    /// A flag indicating if the search dialog is open
    /// </summary>
    protected bool mSearchIsOpen;

    #endregion

    #region Public Properties

    /// <summary>
    /// The chat thread items for the list
    /// NOTE: Do not call Items.Add to add messages to this list
    ///       as it will make the FilteredItems out of sync
    /// </summary>
    public ObservableCollection<ChatMessageListItemViewModel> Items
    {
        get => mItems;
        set
        {
            // Make sure list has changed
            if (mItems == value)
                return;

            // Update value
            mItems = value;

            // Update filtered list to match
            FilteredItems = new ObservableCollection<ChatMessageListItemViewModel>(mItems);
        }
    }

    /// <summary>
    /// The chat thread items for the list that include any search filtering
    /// </summary>
    public ObservableCollection<ChatMessageListItemViewModel> FilteredItems { get; set; }

    /// <summary>
    /// The title of this chat list
    /// </summary>
    public string DisplayTitle { get; set; }

    /// <summary>
    /// True to show the attachment menu, false to hide it
    /// </summary>
    public bool AttachmentMenuVisible { get; set; }

    /// <summary>
    /// True if any pop-up menus are visible
    /// </summary>
    public bool AnyPopupVisible => AttachmentMenuVisible;

    /// <summary>
    /// The view model for the attachment menu
    /// </summary>
    //public ChatAttachmentPopupMenuViewModel AttachmentMenu { get; set; }

    /// <summary>
    /// The text for the current message being written
    /// </summary>
    public string PendingMessageText { get; set; }

    /// <summary>
    /// The text to search for when we do a search
    /// </summary>
    public string SearchText
    {
        get => mSearchText;
        set
        {
            // Check value is different
            if (mSearchText == value)
                return;

            // Update value
            mSearchText = value;

            // If the search text is empty...
            if (string.IsNullOrEmpty(SearchText))
                // Search to restore messages
                OnSearch();
        }
    }

    /// <summary>
    /// A flag indicating if the search dialog is open
    /// </summary>
    public bool SearchIsOpen
    {
        get => mSearchIsOpen;
        set
        {
            // Check value has changed
            if (mSearchIsOpen == value)
                return;

            // Update value
            mSearchIsOpen = value;

            // If dialog closes...
            if (!mSearchIsOpen)
                // Clear search text
                SearchText = string.Empty;
        }
    }

    #endregion

    #region Constructor

    /// <summary>
    /// Default constructor
    /// </summary>
    public ChatMessageListViewModel()
    {
        // Make a default menu
        //AttachmentMenu = new ChatAttachmentPopupMenuViewModel();
    }

    #endregion

    #region Command Methods

    /// <summary>
    /// When the attachment button is clicked show/hide the attachment pop-up
    /// </summary>
    [RelayCommand]
    private void OnAttachmentButton()
    {
        // Toggle menu visibility
        AttachmentMenuVisible ^= true;
    }

    /// <summary>
    /// When the pop-up click away area is clicked hide any pop-ups
    /// </summary>
    [RelayCommand]
    private void OnPopupClickaway()
    {
        // Hide attachment menu
        AttachmentMenuVisible = false;
    }

    /// <summary>
    /// When the user clicks the send button, sends the message
    /// </summary>
    [RelayCommand]
    private void OnSend()
    {
        // Don't send a blank message
        if (string.IsNullOrEmpty(PendingMessageText))
            return;

        // Ensure lists are not null
        if (Items == null)
            Items = new ObservableCollection<ChatMessageListItemViewModel>();

        if (FilteredItems == null)
            FilteredItems = new ObservableCollection<ChatMessageListItemViewModel>();

        // Fake send a new message
        var message = new ChatMessageListItemViewModel
        {
            Initials = "LM",
            Message = PendingMessageText,
            MessageSentTime = DateTime.UtcNow,
            SentByMe = true,
            SenderName = "Luke Malpass",
            NewItem = true
        };

        // Add message to both lists
        Items.Add(message);
        FilteredItems.Add(message);

        // Clear the pending message text
        PendingMessageText = string.Empty;
    }

    /// <summary>
    /// Searches the current message list and filters the view
    /// </summary>
    [RelayCommand]
    private void OnSearch()
    {
        // Make sure we don't re-search the same text
        if ((string.IsNullOrEmpty(mLastSearchText) && string.IsNullOrEmpty(SearchText)) ||
            string.Equals(mLastSearchText, SearchText))
            return;

        // If we have no search text, or no items
        if (string.IsNullOrEmpty(SearchText) || Items == null || Items.Count <= 0)
        {
            // Make filtered list the same
            FilteredItems =
                new ObservableCollection<ChatMessageListItemViewModel>(Items ??
                                                                       Enumerable
                                                                           .Empty<ChatMessageListItemViewModel>());

            // Set last search text
            mLastSearchText = SearchText;

            return;
        }

        // Find all items that contain the given text
        // TODO: Make more efficient search
        FilteredItems = new ObservableCollection<ChatMessageListItemViewModel>(
            Items.Where(item => item.Message.ToLower().Contains(SearchText)));

        // Set last search text
        mLastSearchText = SearchText;
    }

    /// <summary>
    /// Clears the search text
    /// </summary>
    [RelayCommand]
    private void OnClearSearch()
    {
        // If there is some search text...
        if (!string.IsNullOrEmpty(SearchText))
            // Clear the text
            SearchText = string.Empty;
        // Otherwise...
        else
            // Close search dialog
            SearchIsOpen = false;
    }

    /// <summary>
    /// Opens the search dialog
    /// </summary>
    [RelayCommand]
    private void OnOpenSearch() => SearchIsOpen = true;

    /// <summary>
    /// Closes the search dialog
    /// </summary>
    [RelayCommand]
    private void OnCloseSearch() => SearchIsOpen = false;

    #endregion
}